package node;

import lexer.LexType;
import parser.Parser;
import symbol.ArraySymbol;
import symbol.BasicSymbol;
import symbol.ScopeStack;
import symbol.Symbol;

import java.io.IOException;

public class LValNode extends ASTNode {
    public final String name = "<LVal>";
    // LVal → Ident ['[' Exp ']']
    private final String identNode;
    private ExpNode expNode;
    private int lineno;

    private ScopeStack scopeStack = ScopeStack.getInstance();

    public LValNode(String identNode) {
        this.identNode = identNode;
    }

    public LValNode(String identNode, ExpNode expNode) {
        this.identNode = identNode;
        this.expNode = expNode;
    }

    public String getIdentNode() {
        return identNode;
    }

    public int getLineno() {
        return lineno;
    }

    public ExpNode getExpNode() {
        return expNode;
    }

    public void setLineno(int lineno) {
        this.lineno = lineno;
    }

    @Override
    public void show() throws IOException {
        Parser.parserWriter.write(LexType.IDENFR + " " + identNode + "\n");
        if (expNode != null) {
            Parser.parserWriter.write(LexType.LBRACK + " " + "[" + "\n");
            expNode.show();
            Parser.parserWriter.write(LexType.RBRACK + " " + "]" + "\n");
        }
        Parser.parserWriter.write(name + "\n");
    }

    public int calculate() {
        // 计算数组元素的值
        // 这里出现的可以保证是静态的、确定的、非数组的、普通常量名
        // 需要从符号表中查找
        // 用lookup而不是getSymbol
        int res = ((BasicSymbol) (scopeStack.lookup(identNode))).getValueNum();
        return res;
    }

    // 当且仅当Exp为空时，Ident可能是数组名，而不是数组元素
    public boolean isMayArray() {
        return expNode == null;
    }

    public boolean canCaclulate() {
        // 从符号表中查找，如果找到的符号是常量，那么可以计算
        Symbol symbol = scopeStack.lookup(identNode);
        if (symbol instanceof BasicSymbol) {
            if (((BasicSymbol) symbol).canCaclulate()) {
                return true;
            }
        } else if (symbol instanceof ArraySymbol) {
            if (((ArraySymbol) symbol).canCaclulate() && expNode.canCaclulate()) {
                return true;
            }
        }
        return false;
    }
}
